package com.wang.luntan.common.util;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 模拟浏览器请求任何一个网址
 *
 * @author Wangsh
 */
@Component("httpUtil")
@Log4j2
public class HttpUtil {
    @Autowired
    private FileUtil fileUtil;
    public class TrustAnyHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            // 直接返回true
            return true;
        }
    }

    /**
     * 输入一个url,
     * 返回这个url对应的html代码
     *
     * @param urlStr:网址
     * @param headerMap   请求头
     * @param paramsMap   请求体
     * @param responseMap 响应头
     * @return 返回网址对应的html代码
     */
    public String methodGet(String urlStr, Map<String, String> headerMap,
                            Map<String, String> paramsMap, Map<String, String> responseMap) {
        StringBuffer sb = new StringBuffer();
        StringBuffer paramssb = new StringBuffer();
        paramssb.append(urlStr);
        if (!paramssb.toString().endsWith("?") && paramsMap.size() > 0) {
            paramssb.append("?");
        }
        for (Iterator iterator = paramsMap.entrySet().iterator(); iterator
                .hasNext(); ) {
            Map.Entry me = (Map.Entry) iterator.next();
            String key = me.getKey() + "";
            String value = me.getValue() + "";
            key = key.trim();
            value = value.trim();
            paramssb.append(key + "=" + value + "&");
        }

        if (paramssb.toString().endsWith("&")) {
            paramssb.delete(paramssb.length() - 1, paramssb.length());
        }

        // 连续请求多次
        for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++) {
            /* 起始时间戳 */
            long st = System.currentTimeMillis();
            /* 结束时间戳 */
            long ed = 0;
            BufferedReader br = null;
            try {
                sb.delete(0, sb.length());
                URL url = new URL(paramssb.toString());
                HttpURLConnection connection = (HttpURLConnection) this.newConnection(url, headerMap);

                HttpURLConnection.setFollowRedirects(false);
                connection.setInstanceFollowRedirects(false);

                /* Post请求,必须加以下操作 */
                connection.setRequestMethod("GET");

                /* 设置公共的请求头 */
                this.setCommonHeader(headerMap, connection);

                /* 设置请求头 */
                for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext(); ) {
                    Entry me = (Entry) iterator.next();
                    String key = me.getKey() + "";
                    String value = me.getValue() + "";
                    key = key.trim();
                    value = value.trim();
                    if (!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE)) {
                        connection.setRequestProperty(key, value);
                    }
                }

                /* 获取网址对应的输入流和输出流 */
                InputStream is = connection.getInputStream();

                //响应码成功
                if (connection.getResponseCode() == 200) {
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                } else {
                    if (connection.getErrorStream() != null) {
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    } else {
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    }
                }

                String line = "";
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }

                /* 放置响应头 */
                this.responseHeaderSave(headerMap, responseMap, connection);

                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                //log.info("响应体:{}",sb.toString());
                log.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}", i, (ed - st), urlStr, headerMap, paramsMap, responseMap);
                /* 检查网络 */
                this.noNetWork(true);
                /* 请求成功就退出 */
                break;
            } catch (UnknownHostException | SocketTimeoutException e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
                /* 检查网络 */
                this.noNetWork(false);
            } catch (Exception e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
            } finally {
                /* 关闭流 */
                this.fileUtil.closeCharAll(br, null);
            }

            //重试机制
            if ("false".equalsIgnoreCase(headerMap.get("retry"))) {
                /* 默认不重试 */
                break;
            }
        }
        return sb.toString();
    }

    /**
     * 输入一个url,
     * 返回这个url对应的html代码
     *
     * @param urlStr:网址
     * @param headerMap   请求头
     * @param paramsMap   请求体
     * @param responseMap 响应头
     * @return 返回网址对应的html代码
     */
    public String methodPost(String urlStr, Map<String, String> headerMap,
                             Map<String, String> paramsMap, Map<String, String> responseMap) {
        //如果是https协议
//		if(urlStr.startsWith("https"))
//		{
//			return this.methodHttpsPost(urlStr,headerMap, paramsMap,responseMap);
//		}
        StringBuffer sb = new StringBuffer();
        // 连续请求多次
        for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++) {
            /* 起始时间戳 */
            long st = System.currentTimeMillis();
            /* 结束时间戳 */
            long ed = 0;
            BufferedReader br = null;
            BufferedWriter bw = null;
            try {
                URL url = new URL(urlStr);
                HttpURLConnection connection = (HttpURLConnection) this.newConnection(url, headerMap);
                ;

                HttpURLConnection.setFollowRedirects(false);
                connection.setInstanceFollowRedirects(false);

                /* Post请求,必须加以下操作 */
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setRequestMethod("POST");

                /* 设置公共的请求头 */
                this.setCommonHeader(headerMap, connection);
                /* 设置请求头 */
                for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext(); ) {
                    Entry me = (Entry) iterator.next();
                    String key = me.getKey() + "";
                    String value = me.getValue() + "";
                    key = key.trim();
                    value = value.trim();
                    if (!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE)) {
                        connection.setRequestProperty(key, value);
                    }
                }
                /* 获取网址对应的输入流和输出流 */
                OutputStream os = connection.getOutputStream();
                bw = new BufferedWriter(new OutputStreamWriter(os, "UTF-8"));

                /* 先向服务器写数据
                 * 如何将我们的参数写到输出流呢???
                 * 得遵循HTTP协议,看浏览器怎么做,我们也怎么做
                 *
                 * URL get中的字符串
                 * method=submit&email=aaa&password=bbbb
                 *  */
                StringBuffer paramSb = new StringBuffer();
                for (Iterator iterator = paramsMap.entrySet().iterator(); iterator.hasNext(); ) {
                    Entry me = (Entry) iterator.next();
                    String key = me.getKey() + "";
                    String value = me.getValue() + "";
                    key = key.trim();
                    value = value.trim();
                    if (key.equals("")) {
                        paramSb.append(value);
                    } else {
                        paramSb.append(key + "=" + value + "&");
                    }
                }
                /*
                 * method=submit&email=aaa&password=bbbb
                 * email=bb&method=submit&password=cc
                 * */
                bw.write(paramSb.toString());
                bw.flush();
                bw.close();

                /* 获取网址对应的输入流和输出流 */
                InputStream is = connection.getInputStream();

                //响应码成功
                if (connection.getResponseCode() == 200) {
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                } else {
                    if (connection.getErrorStream() != null) {
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    } else {
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    }
                }

                String line = "";
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }

                responseHeaderSave(headerMap, responseMap, connection);
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                //log.info("响应体:{}",sb.toString());
                log.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}", i, (ed - st), urlStr, headerMap, paramsMap, responseMap);
                /* 检查网络 */
                this.noNetWork(true);
                /* 请求成功就退出 */
                break;
            } catch (UnknownHostException | SocketTimeoutException e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
                /* 检查网络 */
                this.noNetWork(false);
            } catch (Exception e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
            } finally {
                /* 关闭流 */
                this.fileUtil.closeCharAll(br, null);
            }

            if ("false".equalsIgnoreCase(headerMap.get("retry"))) {
                /* 默认不重试 */
                break;
            }
        }
        return sb.toString();
    }


    /**
     * 输入一个url,
     * 返回这个url对应的html代码
     *
     * @param urlStr:网址
     * @param headerMap   请求头
     * @param paramsMap   请求体
     * @param responseMap 响应头
     * @return 返回网址对应的html代码
     */
    public String methodHttpsGet(String urlStr, Map<String, String> headerMap,
                                 Map<String, String> paramsMap, Map<String, String> responseMap) {
        //log.info("--methodGet--url:{}",urlStr);
        StringBuffer sb = new StringBuffer();

        StringBuffer paramssb = new StringBuffer();
        paramssb.append(urlStr);
        if (!paramssb.toString().endsWith("?") && paramsMap.size() > 0) {
            paramssb.append("?");
        }
        for (Iterator iterator = paramsMap.entrySet().iterator(); iterator
                .hasNext(); ) {
            Map.Entry me = (Map.Entry) iterator.next();
            String key = me.getKey() + "";
            String value = me.getValue() + "";
            key = key.trim();
            value = value.trim();
            paramssb.append(key + "=" + value + "&");
        }

        if (paramssb.toString().endsWith("&")) {
            paramssb.delete(paramssb.length() - 1, paramssb.length());
        }
        // 连续请求多次
        for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++) {
            /* 起始时间戳 */
            long st = System.currentTimeMillis();
            /* 结束时间戳 */
            long ed = 0;
            BufferedReader br = null;
            try {
                /*========https配置开始=========*/
                // Create a trust manager that does not validate certificate chains
                TrustManager[] trustAllCerts = new TrustManager[]
                        {new X509TrustManager() {
                            public X509Certificate[] getAcceptedIssuers() {
                                return null;
                            }

                            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            }

                            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            }
                        }};

                // Install the all-trusting trust manager
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(null, trustAllCerts, new SecureRandom());
                HttpsURLConnection
                        .setDefaultSSLSocketFactory(sc.getSocketFactory());
                /*========https配置结束=========*/
                URL url = new URL(paramssb.toString());
                HttpsURLConnection connection = (HttpsURLConnection) this.newConnection(url, headerMap);
                /* ==connection常见的配置== */
                connection.setHostnameVerifier(new TrustAnyHostnameVerifier());

                HttpURLConnection.setFollowRedirects(false);
                connection.setInstanceFollowRedirects(false);

                /* Post请求,必须加以下操作 */
                connection.setRequestMethod("GET");

                /* 设置公共的请求头 */
                this.setCommonHeader(headerMap, connection);
                /* 设置请求头 */
                for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext(); ) {
                    Entry me = (Entry) iterator.next();
                    String key = me.getKey() + "";
                    String value = me.getValue() + "";
                    key = key.trim();
                    value = value.trim();
                    if (!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE)) {
                        connection.setRequestProperty(key, value);
                    }
                }
                /* 获取网址对应的输入流和输出流 */
                InputStream is = connection.getInputStream();

                //响应码成功
                if (connection.getResponseCode() == 200) {
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                } else {
                    if (connection.getErrorStream() != null) {
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    } else {
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    }
                }

                String line = "";
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }

                /* 放置响应头 */
                this.responseHeaderSave(headerMap, responseMap, connection);
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                //log.info("响应体:{}",sb.toString());
                log.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}", i, (ed - st), urlStr, headerMap, paramsMap, responseMap);
                /* 检查网络 */
                this.noNetWork(true);
                /* 请求成功就退出 */
                break;
            } catch (UnknownHostException | SocketTimeoutException e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
                /* 检查网络 */
                this.noNetWork(false);
            } catch (Exception e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
            } finally {
                /* 关闭流 */
                this.fileUtil.closeCharAll(br, null);
            }

            //重试机制
            if ("false".equalsIgnoreCase(headerMap.get("retry"))) {
                /* 默认不重试 */
                break;
            }
        }
        return sb.toString();
    }

    /**
     * 输入一个url,
     * 返回这个url对应的html代码
     *
     * @param urlStr:网址
     * @param headerMap   请求头
     * @param paramsMap   请求体
     * @param responseMap 响应头
     * @return 返回网址对应的html代码
     */
    public String methodGet(String urlStr, Map<String, String> headerMap,
                            Map<String, String> paramsMap, Map<String, String> responseMap,
                            String charset) {
        //log.info("--methodGet--url:{}",urlStr);
        if (charset == null || "".equalsIgnoreCase(charset)) {
            charset = ConstatFinalUtil.CHARSET;
        }
        //如果是https协议
//		if(urlStr.startsWith("https"))
//		{
//			return this.methodHttpsGet(urlStr,headerMap, paramsMap,responseMap);
//		}
        StringBuffer sb = new StringBuffer();
        StringBuffer paramssb = new StringBuffer();
        paramssb.append(urlStr);
        if (!paramssb.toString().endsWith("?") && paramsMap.size() > 0) {
            paramssb.append("?");
        }
        for (Iterator iterator = paramsMap.entrySet().iterator(); iterator
                .hasNext(); ) {
            Map.Entry me = (Map.Entry) iterator.next();
            String key = me.getKey() + "";
            String value = me.getValue() + "";
            key = key.trim();
            value = value.trim();
            paramssb.append(key + "=" + value + "&");
        }

        if (paramssb.toString().endsWith("&")) {
            paramssb.delete(paramssb.length() - 1, paramssb.length());
        }

        // 连续请求多次
        for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++) {
            /* 起始时间戳 */
            long st = System.currentTimeMillis();
            /* 结束时间戳 */
            long ed = 0;
            BufferedReader br = null;
            try {
                sb.delete(0, sb.length());
                URL url = new URL(paramssb.toString());
                HttpURLConnection connection = (HttpURLConnection) this.newConnection(url, headerMap);

                /* 设置公共的请求头 */
                this.setCommonHeader(headerMap, connection);

                HttpURLConnection.setFollowRedirects(false);
                connection.setInstanceFollowRedirects(false);

                /* Post请求,必须加以下操作 */
                connection.setRequestMethod("GET");

                /* 设置请求头 */
                for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext(); ) {
                    Entry me = (Entry) iterator.next();
                    String key = me.getKey() + "";
                    String value = me.getValue() + "";
                    key = key.trim();
                    value = value.trim();
                    if (!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE)) {
                        connection.setRequestProperty(key, value);
                    }
                }

                /* 获取网址对应的输入流和输出流 */
                InputStream is = connection.getInputStream();

                //响应码成功
                if (connection.getResponseCode() == 200) {
                    br = new BufferedReader(new InputStreamReader(is, charset));
                } else {
                    if (connection.getErrorStream() != null) {
                        br = new BufferedReader(new InputStreamReader(is, charset));
                    } else {
                        br = new BufferedReader(new InputStreamReader(is, charset));
                    }
                }

                String line = "";
                while ((line = br.readLine()) != null) {
                    sb.append(line);
                }

                /* 放置响应头 */
                this.responseHeaderSave(headerMap, responseMap, connection);

                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                //log.info("响应体:{}",sb.toString());
                log.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}", i, (ed - st), urlStr, headerMap, paramsMap, responseMap);
                /* 检查网络 */
                this.noNetWork(true);
                /* 请求成功就退出 */
                break;
            } catch (UnknownHostException | SocketTimeoutException e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
                /* 检查网络 */
                this.noNetWork(false);
            } catch (Exception e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
            } finally {
                /* 关闭流 */
                this.fileUtil.closeCharAll(br, null);
            }

            //重试机制
            if ("false".equalsIgnoreCase(headerMap.get("retry"))) {
                /* 默认不重试 */
                break;
            }
        }
        return sb.toString();
    }

    /**
     * HttpsPost请求
     *
     * @param headerMap 请求头参数
     * @param paramsMap 请求体参数
     * @return
     */
    public String methodHttpsPost(String urlStr, Map<String, String> headerMap,
                                  Map<String, String> paramsMap, Map<String, String> responseMap) {
        StringBuffer sb = new StringBuffer();
        HttpsURLConnection connection = null;
        // 连续请求多次
        for (int i = 0; i < ConstatFinalUtil.REQ_COUNT; i++) {
            /* 起始时间戳 */
            long st = System.currentTimeMillis();
            /* 结束时间戳 */
            long ed = 0;
            BufferedReader br = null;
            BufferedWriter bw = null;
            try {
                /*========https配置开始=========*/
                // Create a trust manager that does not validate certificate chains
                TrustManager[] trustAllCerts = new TrustManager[]
                        {new X509TrustManager() {
                            public X509Certificate[] getAcceptedIssuers() {
                                return null;
                            }

                            public void checkClientTrusted(X509Certificate[] certs, String authType) {
                            }

                            public void checkServerTrusted(X509Certificate[] certs, String authType) {
                            }
                        }};

                // Install the all-trusting trust manager
                SSLContext sc = SSLContext.getInstance("TLS");
                sc.init(null, trustAllCerts, new SecureRandom());
                HttpsURLConnection
                        .setDefaultSSLSocketFactory(sc.getSocketFactory());
                /*========https配置结束=========*/
                /* 创建Url */
                URL url = new URL(urlStr);
                /* 获取链接 */
                connection = (HttpsURLConnection) this.newConnection(url, headerMap);
                connection.setHostnameVerifier(new TrustAnyHostnameVerifier());

                /* Post请求,必须加以下操作 */
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setRequestMethod("POST");

                /* 先向服务器写数据
                 * 如何将我们的参数写到输出流呢???
                 * 得遵循HTTP协议,看浏览器怎么做,我们也怎么做
                 *
                 * URL get中的字符串
                 * method=submit&email=aaa&password=bbbb
                 *  */
                StringBuffer paramSb = new StringBuffer();
                for (Iterator iterator = paramsMap.entrySet().iterator(); iterator.hasNext(); ) {
                    Entry me = (Entry) iterator.next();
                    String key = me.getKey() + "";
                    String value = me.getValue() + "";
                    key = key.trim();
                    value = value.trim();
                    if (key.equals("")) {
                        paramSb.append(value);
                    } else {
                        paramSb.append(key + "=" + value + "&");
                    }
                }

                if (paramSb.toString().endsWith("&")) {
                    paramSb.delete(paramSb.length() - 1, paramSb.length());
                }

                /* 设置公共的请求头 */
                this.setCommonHeader(headerMap, connection);
                /* 设置请求头 */
                for (Iterator iterator = headerMap.entrySet().iterator(); iterator.hasNext(); ) {
                    Entry me = (Entry) iterator.next();
                    String key = me.getKey() + "";
                    String value = me.getValue() + "";
                    key = key.trim();
                    value = value.trim();
                    if (!key.startsWith(ConstatFinalUtil.REQ_HEADER_IGNORE)) {
                        connection.setRequestProperty(key, value);
                    }
                }

                bw = new BufferedWriter(new OutputStreamWriter(
                        connection.getOutputStream()));
                bw.write(paramSb.toString());
                bw.flush();

                /* 获取网址对应的输入流和输出流 */
                InputStream is = connection.getInputStream();

                //响应码成功
                if (connection.getResponseCode() == 200) {
                    br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                } else {
                    if (connection.getErrorStream() != null) {
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    } else {
                        br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
                    }
                }

                String line = "";
                while ((line = br.readLine()) != null) {
                    sb.append(line.trim());
                }
                /* 存储响应头 */
                responseHeaderSave(headerMap, responseMap, connection);
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                //log.info("响应体:{}",sb.toString());
                log.info("请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}", i, (ed - st), urlStr, headerMap, paramsMap, responseMap);
                /* 检查网络 */
                this.noNetWork(true);
                /* 请求成功就退出 */
                break;
            } catch (UnknownHostException | SocketTimeoutException e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("无法上网,要切换Ip:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
                /* 检查网络 */
                this.noNetWork(false);
            } catch (Exception e) {
                /* 结束时间戳 */
                ed = System.currentTimeMillis();
                log.error("请求服务报错了:请求次数:{},耗时(毫秒):{},url:{},请求头:{},请求体:{},响应头:{}",
                        i, (ed - st), urlStr, headerMap, paramsMap, responseMap, e);
            } finally {
                /* 关闭流 */
                this.fileUtil.closeCharAll(br, null);
            }

            //重试机制
            if ("false".equalsIgnoreCase(headerMap.get("retry"))) {
                /* 默认不重试 */
                break;
            }
        }
        return sb.toString();
    }

    /**
     * 木有网络如何处理
     * netFlag:false,木有链接上网络;true:成功链接上网络
     */
    private void noNetWork(boolean netFlag) {

    }

    /**
     * 存储响应头
     *
     * @param responseMap
     * @param connection
     * @throws IOException
     */
    public void responseHeaderSave(Map<String, String> headerMap, Map<String, String> responseMap, HttpURLConnection connection) throws IOException {
        if (connection != null) {
            responseMap.put("code", connection.getResponseCode() + "");
            /* 把响应头里面的内容放到请求头里面 */
            Map<String, List<String>> headerFieldsMap = connection.getHeaderFields();
            for (Iterator iterator = headerFieldsMap.entrySet().iterator(); iterator.hasNext(); ) {
                Entry me = (Entry) iterator.next();
                String key = me.getKey() + "";
                List<String> valList = (List<String>) me.getValue();
                StringBuffer valSb = new StringBuffer();
                for (Iterator iterator2 = valList.iterator(); iterator2.hasNext(); ) {
                    String valTemp = (String) iterator2.next();
                    valSb.append(valTemp + ConstatFinalUtil.SPLIT_STR);
                }
                responseMap.put(key, valSb.toString());
            }
        }

        /* 处理目标的Cookie */
        String cookieTarget = responseMap.get("Set-Cookie");
        String domain = headerMap.get(ConstatFinalUtil.REQ_HEADER_IGNORE + "domain");
        /* 处理Cookie */
        Map<String, String> resultMap = new HashMap<String, String>();
        /* 处理原始的Cookie,饼干插件需要的 */
        JSONArray cookieArr = this.proccedCookieResponse(cookieTarget, domain, resultMap);
        responseMap.put("cookieArr", cookieArr.toJSONString());
        /* 合并Cookie */
        String cookieRes = resultMap.get("cookieRes");
        List<String> keySearchList = new ArrayList<String>();
        List<String> valueSearchList = new ArrayList<String>();
        /* 合并Cookie */
        cookieRes = this.cookieMerge(headerMap, cookieRes, keySearchList, valueSearchList);
        /* 存储处理过以后的Cookie */
        responseMap.put("cookieTarget", cookieRes);
    }

    /**
     * 设置代理
     *
     * @throws xception
     */
    private URLConnection newConnection(URL url, Map<String, String> headerMap) throws Exception {
        if ("true".equalsIgnoreCase(headerMap.get(ConstatFinalUtil.REQ_HEADER_IGNORE + "proxy"))) {
            String ip = headerMap.get(ConstatFinalUtil.REQ_HEADER_IGNORE + "ip");
            int port = Integer.valueOf(headerMap.get(ConstatFinalUtil.REQ_HEADER_IGNORE + "port"));
            Proxy proxy = new Proxy(Type.SOCKS, new InetSocketAddress(ip, port));

            /* 移除代理 */
            headerMap.remove(ConstatFinalUtil.REQ_HEADER_IGNORE + "proxy");
            headerMap.remove(ConstatFinalUtil.REQ_HEADER_IGNORE + "ip");
            headerMap.remove(ConstatFinalUtil.REQ_HEADER_IGNORE + "port");
            /* 设置代理 */
            return url.openConnection(proxy);
        } else {
            return url.openConnection();
        }
    }

    /**
     * 设置公共的请求头
     *
     * @param headerMap
     */
    public void setCommonHeader(Map<String, String> headerMap, URLConnection connection) {
        String readTimeout = ConstatFinalUtil.REQ_HEADER_IGNORE + "read_timeout";
        if (headerMap.get(readTimeout) != null) {
            /* 设置读取超时 */
            connection.setReadTimeout(Integer.valueOf(headerMap.get(readTimeout)));
        } else {
            connection.setReadTimeout(ConstatFinalUtil.READ_TIMEOUT);
        }
        String reqConnectTimeout = ConstatFinalUtil.REQ_HEADER_IGNORE + "req_connect_timeout";
        if (headerMap.get(reqConnectTimeout) != null) {
            /* 设置请求超时 */
            connection.setConnectTimeout(Integer.valueOf(headerMap.get(reqConnectTimeout)));
        } else {
            connection.setConnectTimeout(ConstatFinalUtil.REQ_CONNECT_TIMEOUT);
        }

        headerMap.remove("host");
        headerMap.remove("referer");
        headerMap.remove("content-security-policy");
        headerMap.remove("origin");
        headerMap.remove("accept-encoding");
        /* 移除代理 */
//		headerMap.remove("via");
//		headerMap.remove("x-proxy-id");

        /*==设置公共的请求头==*/
//		try
//		{
//			if("facebook".equalsIgnoreCase(headerMap.get("commonHeader")))
//			{
//				for (Iterator iterator = ConstatFinalUtil.FACEBOOK_HEADER_JSON.entrySet().iterator(); iterator.hasNext();)
//				{
//					Entry me = (Entry) iterator.next();
//					String key = me.getKey() + "" ; 
//					String val = me.getValue() + "" ; 
//					headerMap.put(URLEncoder.encode(key, "UTF-8"), val);
//				}
//				
//				/* 移除代理 */
//				headerMap.remove("commonHeader");
//			}
//		} catch (Exception e)
//		{
//			log.error("设置请求转码失败:",e);
//		}

        /* 设置Ip;伪造Ip */
        String ip = headerMap.get("ip");
        String clientIp = headerMap.get("clientIp");
        if (ip == null) {
            ip = "";
        }
        if (clientIp != null && !"".equalsIgnoreCase(clientIp) && !"null".equalsIgnoreCase(clientIp)) {
            ip = clientIp;
        }
        /* 移除Ip */
        headerMap.remove("ip");
        headerMap.remove("clientIp");
//		if(!"null".equalsIgnoreCase(ip) && !"".equalsIgnoreCase(ip))
//		{
//			headerMap.put("x-real-ip", ip);
//			headerMap.put("x-forwarded-for", ip);
//			headerMap.put("http_x_forwarded_for", ip);
//			headerMap.put("http_client_ip", ip);
//			headerMap.put("remote_addr", ip);
//			headerMap.put("host", ip);
//			headerMap.put("proxy-client-ip", ip);
//			headerMap.put("wl-proxy-client-ip", ip);
//			headerMap.put("ip", ip);
//			headerMap.put("http_cf_connecting_ip", ip);
//		}

        /* 去掉那些包含关键字的cookei */
        String cookieRes = "";
        List<String> keyList = new ArrayList<String>();
        List<String> valList = new ArrayList<String>();
        cookieRes = this.cookieMerge(headerMap, cookieRes, keyList, valList);
        headerMap.put("cookie", cookieRes);
    }

    /**
     * 生成一个新的Cookie
     *
     * @return
     */
    public String newCookieStr(String path) {
        String cookie = "JSESSIONID=" + UUID.randomUUID().toString();
        return cookie;
//		String sufix = ";Path="+ path +"; HttpOnly";
//		return cookie + sufix ; 
    }

    /**
     * 传入请求头的Cookie和响应头的Cookie,合并一下
     * 如果cookieRes要是木有值,就和Cookie一样就可以
     *
     * @return
     */
    public String cookieMerge(Map<String, String> headerMap, String cookieRes,
                              List<String> keySearchList, List<String> valueSearchList) {
        /* 判断值 */
        String searchStr = "deleted";
        /* 判断键 */
        //String keySearch = "checkpoint" ;

        valueSearchList.add(searchStr);
        //keySearchList.add(keySearch);
        /* 最终的Cookie
         * fr=aa;sb=bb;fr=delete
         *  */
        String cookieHeader = headerMap.get("cookie");
        if (cookieHeader == null || "".equalsIgnoreCase(cookieHeader)) {
            /* 如果目标的cookie要是木有值,直接和原来的cookie一样 */
            cookieHeader = this.newCookieStr("/");
        }

        if (cookieRes == null || "".equalsIgnoreCase(cookieRes)) {
            /* 如果目标的cookie要是木有值,直接和原来的cookie一样 */
            cookieRes = cookieHeader;
        }

        Map<String, String> cookieHeaderMap = this.cookieSplit(cookieHeader);
        /* 响应头中的Cookie */
        Map<String, String> cookieResMap = this.cookieSplit(cookieRes);
        /* 找出响应头中Cookie带delete字样的 */
        for (Iterator iterator = cookieResMap.entrySet().iterator(); iterator.hasNext(); ) {
            Entry me = (Entry) iterator.next();
            String key = me.getKey() + "";
            String value = me.getValue() + "";
            key = key.trim();
            value = value.trim();
            if (keySearchList.contains(key) || valueSearchList.contains(value)) {
                /* 说明已经删除了 */
                cookieHeaderMap.remove(key);
            } else {
                cookieHeaderMap.put(key, value);
            }
        }
        /* 拼装最终想要的Cookie */
        StringBuffer sb = new StringBuffer();
        for (Iterator iterator = cookieHeaderMap.entrySet().iterator(); iterator.hasNext(); ) {
            Entry me = (Entry) iterator.next();
            String key = me.getKey() + "";
            String value = me.getValue() + "";
            sb.append(key.trim() + "=" + value.trim() + ";");
        }
        return sb.toString();
    }

    /**
     * Cookie拆分
     *
     * @param headerMap
     * @param keyword
     * @return
     */
    public Map<String, String> cookieSplit(String cookie) {
        Map<String, String> resultMap = new HashMap<String, String>();
        if (cookie != null && !"".equalsIgnoreCase(cookie)) {
            /* 切分Cookie */
            String[] cookies = cookie.split(";");
            for (int i = 0; i < cookies.length; i++) {
                String cookieTemp = cookies[i];
                String[] splits = cookieTemp.split("=");
                if (splits.length == 2) {
                    resultMap.put(splits[0].trim(), splits[1].trim());
                }
            }
        }
        return resultMap;
    }

    /**
     * 处理服务器响应端的Cookie
     *
     * @param cookieRes 存储Cookie的结果
     * @param cookie    响应的Cookie格式的字符串
     * @param domain    cookie的域名
     * @return 拼装成饼干插件需要的JSON
     */
    public JSONArray proccedCookieResponse(String cookie, String domain, Map<String, String> resultMap) {
        String cookieRes = "";
        JSONArray cookieArr = new JSONArray();
        if (cookie != null) {
            String[] cookies = cookie.split(ConstatFinalUtil.SPLIT_STR_ZHUAN);
            for (int i = 0; i < cookies.length; i++) {
                /* 原装的Cookie */
                String cookieTemp = cookies[i];
                /* 拼装json */
                JSONObject cookieTempJSON = this.proccedCookieJSON(cookieTemp, domain);
                cookieTempJSON.put("id", i + 1);

                /* 目标的json */
                String cookieTarTemp = cookieTempJSON.getString("name") + "=" + cookieTempJSON.getString("value") + ";";
                /* 拼装json */
                cookieRes = cookieRes + cookieTarTemp;
                cookieArr.add(cookieTempJSON);
            }
        }
        resultMap.put("cookieRes", cookieRes);
        return cookieArr;
    }

    /**
     * 生成一个饼开插件的json
     * {
     * "domain": ".facebook.com",
     * "expirationDate": 1599095052.94666,
     * "hostOnly": false,
     * "httpOnly": false,
     * "name": "c_user",
     * "path": "/",
     * "sameSite": "no_restriction",
     * "secure": true,
     * "session": false,
     * "storeId": "0",
     * "value": "100040966342079",
     * "id": 1
     * }
     *
     * @return
     */
    private JSONObject proccedCookieJSON(String val, String domain) {
        Map<String, String> cookieMap = this.cookieSplit(val);
        /* 把第一行的cookie,变成Map */
        String name = "";
        String equalsIndex = "=";
        if (val.indexOf(equalsIndex) != -1) {
            name = val.substring(0, val.indexOf(equalsIndex));
        }
        JSONObject resultJSON = new JSONObject();
        resultJSON.put("domain", domain);
        /* 有效期为一天;单位是秒 */
        long maxAge = 1000;
        if (cookieMap.get("Max-Age") != null) {
            maxAge = Long.valueOf(cookieMap.get("Max-Age") + "");
        }
        resultJSON.put("expirationDate", System.currentTimeMillis() / 1000 + maxAge);
        /* hostOnly  */
        String hostOnly = "hostOnly";
        if (cookieMap.get(hostOnly) != null) {
            resultJSON.put(hostOnly, true);
        } else {
            resultJSON.put(hostOnly, false);
        }

        /* httpOnly  */
        String httpOnly = "httpOnly";
        if (cookieMap.get(httpOnly) != null) {
            resultJSON.put(httpOnly, true);
        } else {
            resultJSON.put(httpOnly, false);
        }
        /* secure  */
        String secure = "secure";
        if (cookieMap.get(secure) != null) {
            resultJSON.put(secure, true);
        } else {
            resultJSON.put(secure, false);
        }
        /* session  */
        String session = "session";
        if (cookieMap.get(session) != null) {
            resultJSON.put(session, true);
        } else {
            resultJSON.put(session, false);
        }

        resultJSON.put("name", name);
        String value = cookieMap.get(name);
        resultJSON.put("value", value);
        resultJSON.put("path", "/");
        resultJSON.put("sameSite", "no_restriction");
        resultJSON.put("storeId", "0");
        return resultJSON;
    }

    /**
     * 设置代理
     *
     * @param headerMap
     */
    public void setProxy(Map<String, String> headerMap) {
        /* 设置代理 */
//		headerMap.put(ConstatFinalUtil.REQ_HEADER_IGNORE + "proxy", "true");
//		headerMap.put(ConstatFinalUtil.REQ_HEADER_IGNORE + "ip", "192.168.100.6");
//		headerMap.put(ConstatFinalUtil.REQ_HEADER_IGNORE + "port", "48333");
    }

    public static void main(String[] args) {
        HttpUtil httpUtil = new HttpUtil();
		
		/*String url = "http://c.v.qq.com/vchannelinfo?otype=json&uin=599568d32c9189aaabe3c6c6aff3832c&qm=1&pagenum=3&num=10&sorttype=0&orderflag=0&callback=jQuery191013239971445429688_1498793173745&low_login=1&_=1498793173756" ; 
		String res = httpUtil.methodGet(url);
		System.out.println(res);*/

        String url = "http://ip.taobao.com/service/getIpInfo.php";
        Map<String, String> headerMap = new HashMap<String, String>();
        Map<String, String> paramsMap = new HashMap<String, String>();
        Map<String, String> responseMap = new HashMap<String, String>();
        paramsMap.put("ip", "123.14.5.115");
        String res = httpUtil.methodPost(url, headerMap, paramsMap, responseMap);
        System.out.println(res);
    }


}